home *** CD-ROM | disk | FTP | other *** search
- #define VERSION "vvrb 1.01 12-18-85"
-
- /*
- *
- * Code fragments stolen from VMS version of UMODEM.C
- *
- * A program for VMS which can receive
- * files from computers running YAM or MODEM.
- * If no filename is given, YMODEM (YAM batch) protocol is assumed.
- *
- * Supports the CRC option or regular checksum.
- * Received pathnames containing no lowercase letters will be changed
- * to lower case unless -u option is given.
- *
- * Unless the -b (binary) option is given,
- * ^Z (which is discarded) acts as end of file.
- *
- * If the raw pathname ends in any of the extensions in Extensions,
- * or .?Q* (squeezed file), or if the first sector contains binary-like
- * data (parity bits or characters in the range 0 to 6 before ^Z is seen),
- * or if the transmitted file mode has the 0100000 but set,
- * that file will be received in binary mode anyway.
- *
- *
- * A log of activities is appended to LOGFILE with the -v option
- *
- * To compile on VMS:
- * cc vvrb.c
- * cc vvmodem.c
- * link vvrb,vvmodem
- * rb :== $disk$user2:[username.subdir]vvrb.exe
- *
- * Manual page is "rb.1" in the Unix version rbsb.sh file
- */
- #define LOGFILE "rblog"
-
- #include <stdio.h>
- #include <ctype.h>
- #include "vmodem.h"
-
- #ifdef vms
- #include ssdef
- #include tt2def
- #include ttdef
- #define SS_NORMAL SS$_NORMAL
- #else
- #define SS_NORMAL 0
- #endif
-
- /* VMS structures */
- #ifdef vms
- /*
- * TT_INFO structures are used for passing information about
- * the terminal. Used in GTTY and STTY calls.
- */
- struct tt_info ttys, ttysnew, ttystemp;
- #endif
-
- #define OK 0
- #define FALSE 0
- #define TRUE 1
- #define ERROR (-1)
-
- char *substr();
- FILE *fout;
-
- char *Extensions[] = {
- ".A",
- ".ARC",
- ".CCC",
- ".CL",
- ".CMD",
- ".COM",
- ".CRL",
- ".DAT",
- ".DIR",
- ".EXE",
- ".O",
- ".OBJ",
- ".OVL",
- ".PAG",
- ".REL",
- ".SAV",
- ".SUB",
- ".SWP",
- ".SYS",
- ".TAR",
- ".UTL",
- ".a",
- ".o",
- ".tar",
- ""
- };
-
- /* Ward Christensen / CP/M parameters - Don't change these! */
- #define ENQ 005
- #define CAN ('X'&037)
- #define XOFF ('s'&037)
- #define XON ('q'&037)
- #define SOH 1
- #define STX 2
- #define EOT 4
- #define ACK 6
- #define NAK 025
- #define CPMEOF 032
- #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
- #define TIMEOUT (-2)
- #define RETRYMAX 10
- #define WCEOT (-10)
- #define SECSIZ 128 /* cp/m's Magic Number record size */
- #define PATHLEN 257 /* ready for 4.2 bsd ? */
- #define KSIZE 1024 /* record size with k option */
- #define UNIXFILE 0x8000 /* happens to the the S_IFREG file mask bit for stat */
-
- int Lastrx;
- int Crcflg;
- int Firstsec;
- int Eofseen; /* indicates cpm eof (^Z) has been received */
- int totblocks; /* total number of blocks received */
- int errors;
-
- #define DEFBYTL 2000000000L /* default rx file size */
- long Bytesleft; /* number of bytes of incoming file left */
- long Modtime; /* Unix style mod time for incoming file */
- short Filemode; /* Unix style mode for incoming file */
- char Pathname[PATHLEN];
-
- int Batch=0;
- int Wcsmask=0377;
- int MakeLCPathname=TRUE; /* make received pathname lower case */
- int Verbose=0;
- int Quiet=0; /* overrides logic that would otherwise set verbose */
- int Rxbinary=FALSE; /* receive all files in bin mode */
- int Thisbinary; /* current file is to be received in bin mode */
- int Blklen; /* record length of received packets */
- char secbuf[KSIZE];
- char linbuf[KSIZE];
- int Lleft=0; /* number of characters in linbuf */
-
- unsigned short updcrc();
-
- main(argc, argv)
- char *argv[];
- {
- register char *cp;
- register npats;
- char **patts;
- int exitcode;
-
- setbuf(stderr, NULL);
- npats = 0;
- while (--argc) {
- cp = *++argv;
- if (*cp == '-') {
- while( *++cp) {
- switch(*cp) {
- case '7':
- Wcsmask = 0177;
- case 'b':
- Rxbinary=TRUE; break;
- case 'k':
- case 'c':
- Crcflg=TRUE; break;
- case 'q':
- Quiet=TRUE; Verbose=0; break;
- case 'u':
- MakeLCPathname=FALSE; break;
- case 'v':
- ++Verbose; break;
- default:
- usage();
- }
- }
- }
- else if ( !npats && argc>0) {
- if (argv[0][0]) {
- npats=argc;
- patts=argv;
- }
- }
- }
- if (npats > 1)
- usage();
- if (Verbose) {
- if (freopen(LOGFILE, "a", stderr)==NULL) {
- printf("Can't open log file %s\n",LOGFILE);
- exit(SS_NORMAL);
- }
- setbuf(stderr, NULL);
- }
- setmodes();
-
- if (wcreceive(npats, patts)==ERROR) {
- exitcode=0200;
- canit();
- }
- restoremodes(FALSE);
- if (exitcode != 0) /* bellow again with all thy might. */
- canit();
- exit(SS_NORMAL);
- }
-
-
- usage()
- {
- fprintf(stderr,"rb %s by Chuck Forsberg\n", VERSION);
- fprintf(stderr,"Usage: rb [-buv]\n\tor rb [-bcuv] file\n");
- exit(SS_NORMAL);
- }
-
- wcreceive(argc, argp)
- char **argp;
- {
- if (Batch || argc==0) {
- Crcflg=(Wcsmask==0377);
- fprintf(stderr, "rb: ready ");
- for (;;) {
- totblocks=0;
- if (wcrxpn(secbuf)== ERROR)
- goto fubar;
- if (secbuf[0]==0)
- return OK;
- if (procheader(secbuf) == ERROR)
- goto fubar;
- if (wcrx()==ERROR)
- goto fubar;
- }
- } else {
- totblocks=0; Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
-
- strcpy(Pathname, *argp);
- if (fopen(*argp, "r") != NULL) {
- fprintf(stderr, "rb: %s exists\n", Pathname);
- goto fubar;
- }
- fprintf(stderr, "\nrb: ready to receive %s ", Pathname);
- if ((fout=fopen(Pathname, "w")) == NULL)
- return ERROR;
- if (wcrx()==ERROR)
- goto fubar;
- }
- return OK;
- fubar:
- canit();
- if (fout)
- fclose(fout);
- return ERROR;
- }
-
-
- /*
- * Fetch a pathname from the other end as a C ctyle ASCIZ string.
- * Length is indeterminate as long as less than Blklen
- * a null string represents no more files
- */
- wcrxpn(rpn)
- char *rpn; /* receive a pathname */
- {
- register c;
-
- et_tu:
- Firstsec=TRUE;
- sendline(Crcflg?WANTCRC:NAK);
- while ((c = wcgetsec(rpn, 100)) != 0) {
- log( "Pathname fetch returned %d\n", c);
- if (c == WCEOT) {
- sendline(ACK); readline(1); goto et_tu;
- }
- return ERROR;
- }
- sendline(ACK);
- return OK;
- }
-
- /*
- * Adapted from CMODEM13.C, written by
- * Jack M. Wierda and Roderick W. Hart
- */
-
- wcrx()
- {
- register int sectnum, sectcurr;
- register char sendchar;
- register char *p;
- int cblklen; /* bytes to dump this block */
- long timep[2];
-
- Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
- sendchar=Crcflg?WANTCRC:NAK;
-
- for (;;) {
- sendline(sendchar); /* send it now, we're ready! */
- sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
- report(sectcurr);
- if (sectcurr==(sectnum+1 &Wcsmask)) {
-
- if (sectnum==0 && !Thisbinary)
- for (p=secbuf,sectcurr=Blklen;
- *p != 032 && --sectcurr>=0; ++p)
- if (*p < 07 || (*p & 0200)) {
- Thisbinary++;
- if (Verbose)
- fprintf(stderr, "Changed to BIN\n");
- break;
- }
- sectnum++;
- cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
- if (putsec(secbuf, cblklen)==ERROR)
- return ERROR;
- if ((Bytesleft-=cblklen) < 0)
- Bytesleft = 0;
- sendchar=ACK;
- }
- else if (sectcurr==(sectnum&Wcsmask)) {
- log( "Received dup Sector\n");
- sendchar=ACK;
- }
- else if (sectcurr==WCEOT) {
- if (fclose(fout)==ERROR) {
- canit();
- fprintf(stderr, "file close ERROR\n");
- return ERROR;
- }
- if (Modtime) {
- timep[0] = time(NULL);
- timep[1] = Modtime;
- /*
- utime(Pathname, timep);
- */
- }
- if (Filemode)
- chmod(Pathname, (07777 & Filemode));
- sendline(ACK);
- return OK;
- }
- else if (sectcurr==ERROR)
- return ERROR;
- else {
- log( "Sync Error\n");
- return ERROR;
- }
- }
- }
-
- /*
- * wcgetsec fetches a Ward Christensen type sector.
- * Returns sector number encountered or ERROR if valid sector not received,
- * or CAN CAN received
- * or WCEOT if eot sector
- * time is timeout for first char, set to 4 seconds thereafter
- ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
- * (Caller must do that when he is good and ready to get next sector)
- */
-
- wcgetsec(rxbuf, maxtime)
- char *rxbuf;
- int maxtime;
- {
- register checksum, wcj, firstch;
- register unsigned short oldcrc;
- register char *p;
- int sectcurr;
-
- for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
-
- if ((firstch=readline(maxtime))==STX) {
- Blklen=KSIZE; goto get2;
- }
- if (firstch==SOH) {
- Blklen=SECSIZ;
- get2:
- sectcurr=readline(5);
- if ((sectcurr+(oldcrc=readline(5)))==Wcsmask) {
- oldcrc=checksum=0;
- for (p=rxbuf, wcj=Blklen; wcj; wcj -= 128) {
- if (raw_read(128,p,7) == SS$_TIMEOUT) {
- firstch=TIMEOUT; goto bilge;
- }
- p += 128;
- }
- for (p=rxbuf, wcj=Blklen; --wcj>=0; ) {
- firstch = *p++ & Wcsmask;
- oldcrc=updcrc(firstch, oldcrc);
- checksum += (firstch);
- }
- if ((firstch=readline(5)) < 0)
- goto bilge;
- if (Crcflg) {
- oldcrc=updcrc(firstch, oldcrc);
- if ((firstch=readline(5)) < 0)
- goto bilge;
- oldcrc=updcrc(firstch, oldcrc);
- if (oldcrc)
- log("CRC=0%o\n", oldcrc);
- else {
- Firstsec=FALSE;
- return sectcurr;
- }
- }
- else if (((checksum-firstch)&Wcsmask)==0) {
- Firstsec=FALSE;
- return sectcurr;
- }
- else
- log( "Checksum Error\n");
- }
- else
- log("Sector number garbled 0%o 0%o\n",
- sectcurr, oldcrc);
- }
- /* make sure eot really is eot and not just mixmash */
- else if (firstch==EOT && Lleft==0)
- return WCEOT;
- else if (firstch==CAN) {
- if (Lastrx==CAN) {
- log( "Sender CANcelled\n");
- return ERROR;
- } else {
- Lastrx=CAN;
- continue;
- }
- }
- else if (firstch==TIMEOUT) {
- if (Firstsec)
- goto humbug;
- bilge:
- log( "Timeout\n");
- }
- else
- log( "Got 0%o sector header\n", firstch);
-
- humbug:
- Lastrx=0;
- if (firstch != TIMEOUT)
- junkpacket();
- if (Firstsec)
- sendline(Crcflg?WANTCRC:NAK);
- else {
- maxtime=40; sendline(NAK);
- }
- }
- /* try to stop the bubble machine. */
- canit();
- return ERROR;
- }
-
-
- /* update CRC */
- unsigned short
- updcrc(c, crc)
- register c;
- register unsigned crc;
- {
- register count;
-
- for (count=8; --count>=0;) {
- if (crc & 0x8000) {
- crc <<= 1;
- crc += (((c<<=1) & 0400) != 0);
- crc ^= 0x1021;
- }
- else {
- crc <<= 1;
- crc += (((c<<=1) & 0400) != 0);
- }
- }
- return crc;
- }
-
- /*
- * process incoming header
- */
- procheader(name)
- char *name;
- {
- register char *openmode, *p, **pp;
-
- /* set default parameters */
- openmode = "w"; Thisbinary=Rxbinary;
- Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
-
- p = name + 1 + strlen(name);
- if (*p) { /* file coming from Unix type system */
- sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
- if (Filemode & UNIXFILE)
- ++Thisbinary;
- if (Verbose) {
- fprintf(stderr, "Incoming: %s %ld %lo %o\n",
- name, Bytesleft, Modtime, Filemode);
- }
- }
- else { /* File coming from CP/M type system */
- for (p=name; *p; ++p) /* change / to _ */
- if ( *p == '/')
- *p = '_';
-
- if ( *--p == '.') /* zap trailing period */
- *p = 0;
- }
-
- /* scan for extensions that signify a binary file */
- if (p=substr(name, "."))
- for (pp=Extensions; **pp; ++pp)
- if (strcmp(p, *pp)==0) {
- Thisbinary=TRUE; break;
- }
-
- /* scan for files which should be appended */
- if ( !Thisbinary
- && (substr(name, ".TXT")
- || substr(name, ".txt")
- || substr(name, ".MSG")))
- openmode = "a";
- if (MakeLCPathname && !IsAnyLower(name))
- uncaps(name);
- strcpy(Pathname, name);
- if (Verbose) {
- fprintf(stderr, "Receiving %s %s %s\n",
- name, Thisbinary?"BIN":"ASCII", openmode);
- }
- if ((fout=fopen(name, openmode)) == NULL)
- return ERROR;
- return OK;
- }
-
- /* make string s lower case */
- uncaps(s)
- register char *s;
- {
- for ( ; *s; ++s)
- if (isupper(*s))
- *s = tolower(*s);
- }
-
-
- /*
- * IsAnyLower returns TRUE if string s has lower case letters.
- */
- IsAnyLower(s)
- register char *s;
- {
- for ( ; *s; ++s)
- if (islower(*s))
- return TRUE;
- return FALSE;
- }
- /*
- * putsec writes the n characters of buf to receive file fout.
- * If not in binary mode, carriage returns, and all characters
- * starting with CPMEOF are discarded.
- */
- putsec(buf, n)
- char *buf;
- register n;
- {
- register char *p;
-
- ++totblocks;
- if (Thisbinary)
- {
- for (p=buf; --n>=0; )
- putc( *p++, fout);
- }
- else {
- if (Eofseen)
- return OK;
- for (p=buf; --n>=0; ++p ) {
- /*
- if ( *p == '\r')
- continue;
- */
- if (*p == CPMEOF) {
- Eofseen=TRUE; return OK;
- }
- putc(*p ,fout);
- }
- }
- return OK;
- }
-
-
- /*
- * substr(string, token) searches for token in string s
- * returns pointer to token within string if found, NULL otherwise
- */
- char *
- substr(s, t)
- register char *s,*t;
- {
- register char *ss,*tt;
- /* search for first char of token */
- for (ss=s; *s; s++)
- if (*s == *t)
- /* compare token with substring */
- for (ss=s,tt=t; ;) {
- if (*tt == 0)
- return s;
- if (*ss++ != *tt++)
- break;
- }
- return NULL;
- }
-
- /*VARARGS1*/
- log(s,p,u)
- char *s, *p, *u;
- {
- if (!Verbose)
- return;
- fprintf(stderr, "error %d: ", errors);
- fprintf(stderr, s, p, u);
- }
-
- /* send 10 CAN's to try to get the other end to shut up */
- canit()
- {
- register n;
- for (n=10; --n>=0; )
- sendline(CAN);
- }
-
- #ifdef REGULUS
- /*
- * copies count bytes from s to d
- * (No structure assignment in Regulus C compiler)
- */
-
- movmem(s, d, count)
- register char *s, *d;
- register count;
- {
- while (--count >= 0)
- *d++ = *s++;
- }
- #endif
-
-
- report(sct)
- int sct;
- {
- if (Verbose>1)
- fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
- }
-
- /* set tty modes for vvrb transfers */
- setmodes()
- {
- /* Device characteristics for VMS */
- #ifdef vms
- int *iptr, parameters;
-
- /*
- * Get current terminal parameters.
- */
- if (gtty(&ttys) != SS$_NORMAL)
- error("SETMODES: error return from GTTY (1)", FALSE);
- if (gtty(&ttysnew) != SS$_NORMAL)
- error("SETMODES: error return from GTTY (2)", FALSE);
-
- /*
- * Set new terminal parameters.
- * Note that there are three bytes of terminal characteristics,
- * so we should make sure the fourth byte of the integer is unchanged.
- */
- iptr = &(ttysnew.dev_characteristics.bcharacteristics);
- parameters = *iptr;
-
- parameters &= ~TT$M_ESCAPE; /* ESCAPE OFF */
- parameters &= ~TT$M_HOSTSYNC; /* HOSTSYNC OFF */
- parameters |= TT$M_NOECHO; /* NOECHO ON */
- parameters |= TT$M_PASSALL; /* PASSALL ON */
- parameters &= ~TT$M_READSYNC; /* READSYNC OFF */
- parameters &= ~TT$M_TTSYNC; /* TTSYNC OFF */
- parameters &= ~TT$M_WRAP; /* WRAP OFF */
- parameters |= TT$M_EIGHTBIT; /* EIGHTBIT ON */
-
- *iptr = parameters;
-
- if (stty(&ttysnew) != SS_NORMAL)
- error("SETMODES: error return from STTY", TRUE);
- #endif
- }
-
-
-
- /* restore normal tty modes */
- restoremodes(errcall)
- int errcall;
- {
- /* Device characteristic restoration for VMS */
- #ifdef vms
- if (stty(&ttys) != SS_NORMAL) /* Restore original modes */
- {
- if (!errcall)
- error("Error restoring original terminal params.",
- FALSE);
- else
- {
- printf("vvrb/RESTOREMODES: ");
- printf("Error restoring original terminal params.\n");
- }
- }
- #endif
- }
-
- /*
- BBUFSIZ - 128 or 1024 etc.
- raw_read(BBUFSIZ + 7, inbuf, 5 + 3 * (BBUFSIZ + 6));
- */
-
-
-
-
- /* get a byte from data stream -- timeout if "dseconds" elapses */
- /* NOTE, however, that this function returns an INT, not a BYTE!!! */
- readline(dseconds)
- {
- int seconds;
- int c;
-
- seconds = dseconds/10;
- if (seconds < 5)
- seconds = 5;
- #ifdef vms
- c = raw_read(1, &c, seconds);
-
- if (c == SS$_TIMEOUT)
- return(TIMEOUT);
-
- return(c & 0377); /* return the char */
- #endif
- }
-
- /* junkpacket gets the line cleared */
- junkpacket()
- {
- int c;
-
- #ifdef vms
- for (;;) {
- c = raw_read(1, &c, 1);
-
- if (c == SS$_TIMEOUT)
- return;
- }
- #endif
- }
-
- /* send a byte to data stream */
- sendline(data)
- {
- char dataout;
-
- dataout = data;
- #ifdef vms
- raw_write(dataout);
- #endif
-
- }
-
-
- /* print error message and exit; if mode == TRUE, restore normal tty modes */
- error(msg, mode)
- char *msg;
- int mode;
- {
- if (mode)
- restoremodes(TRUE); /* put back normal tty modes */
- printf("vvrb: %s\n", msg);
- exit(SS_NORMAL);
- }